package net.hancl.modules.sys.controller;

import net.hancl.common.bean.ResultBean;
import net.hancl.common.cache.EhCacheKeys;
import net.hancl.common.cache.EhcacheCacheManager;
import net.hancl.common.constants.RespHeaderConstans;
import net.hancl.common.exception.MessageCode;
import net.hancl.common.utils.IpUtil;
import net.hancl.common.utils.http.WebHelp;
import net.hancl.common.utils.spring.SysApplicationContext;
import net.hancl.modules.sys.annotation.CurrentUser;
import net.hancl.modules.sys.bean.UserBean;
import net.hancl.modules.sys.constants.SysComm;
import net.hancl.modules.sys.entity.Menu;
import net.hancl.modules.sys.entity.User;
import net.hancl.modules.sys.exception.CaptchaErrorException;
import net.hancl.modules.sys.service.IMenuService;
import net.hancl.modules.sys.service.IUserLoginService;
import net.hancl.modules.sys.service.IUserService;
import net.hancl.modules.sys.shiro.jcaptcha.Jcaptcha;
import net.hancl.modules.sys.vo.UserLoginVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Controller
public class UserLoginController {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private IUserLoginService userLoginService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IMenuService menuService;


    @RequestMapping(value = "logout", method = RequestMethod.POST)
    @ResponseBody
    public ResultBean logout(HttpServletRequest request, HttpServletResponse response, UserLoginVo userLoginVo) {
        ResultBean rb = new ResultBean();
        try {
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
            rb.setMessageCode(MessageCode.USER_LOGOUT);
            rb.setMessage("退出系统成功");
        } catch (Exception e) {
            logger.error("用户登陆异常:UserName:{} ,Message>>>{}", userLoginVo.getUserName(), e.getMessage());
            e.printStackTrace();
            rb = new ResultBean(false, MessageCode.SYS_ERROR, "异统异常");
        }
        return rb;
    }

    /**
     * 用户登录
     */
    @ResponseBody
    @RequestMapping(value = "login", method = RequestMethod.POST) // , method=RequestMethod.POST
    public ResultBean login(HttpServletRequest request, HttpServletResponse req, UserLoginVo loginUser) {
        ResultBean rb = new ResultBean();

        if (loginUser == null || StringUtils.isBlank(loginUser.getUserName())
                || StringUtils.isBlank(loginUser.getPassword())) {
            rb = new ResultBean(false, MessageCode.PLASS_LOGIN, "请登陆系统", "");
            return rb;
        }

        // 验证码处理
        ResultBean rbBean = capthchaProcess(request, loginUser.getUserName(), loginUser.getCaptcha());
        if (rbBean != null) {
            return rbBean;
        }

        boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
        String host = IpUtil.getRemoteIp(request);
        try {
            UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUserName(), loginUser.getPassword().toCharArray(),
                    rememberMe, host);

            // 发出登陆请求
            Subject sbuject = SecurityUtils.getSubject();
            sbuject.login(token);

            try {
                UserBean user = userService.getUser(loginUser.getUserName());
                List<Menu> menus = userService.getUserMenus(loginUser.getUserName());
                if (menus != null) {
                    user.setMenus(menus);
                }
                rb.setData(user);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw new Exception(e);
            }

        } catch (UnknownAccountException e) {
            rb = new ResultBean(false, MessageCode.SYS_NO_USER, "账号不存在!", "");
        } catch (IncorrectCredentialsException e) {
            rb = new ResultBean(false, MessageCode.SYS_NO_USER_AND_PASSWORD, "用户或密码错误", "");
        } catch (CaptchaErrorException e) {
            rb = new ResultBean(false, MessageCode.PLASS_CAPTCHA, " 请输入验证码", "");
        } catch (ExcessiveAttemptsException e) {
            rb = new ResultBean(false, MessageCode.SYS_LOG_IN_TOO_MANY, "账户错误次数过多,暂时禁止登录!", "");
        } catch (Exception e) {
            rb = new ResultBean(false, MessageCode.SYS_ERROR, "系统异常!");
        }
        return rb;
    }

    @RequestMapping(value = "loginPage") // , method=RequestMethod.POST
    public void loginPage(HttpServletRequest request, HttpServletResponse response) {

        // 获取用户信息 好像没必要 null?
        Subject sbuject = SecurityUtils.getSubject();
        Object principal = sbuject.getPrincipal();
        Map<String, String> map = new HashMap<String, String>();
        if (principal != null && !"".equals(principal)) {
            EhcacheCacheManager cacheManager = (EhcacheCacheManager) SysApplicationContext
                    .getBean("cacheManager");
            Cache<String, AtomicInteger> cache = cacheManager.getCache(EhCacheKeys.LONGIN_COUNT);
            AtomicInteger loginCount = cache.get(principal.toString());
            if (loginCount != null && loginCount.get() >= SysComm.USER_LOGIN_COUNT) {
                map.put("isCaptcha", "1");

            }

        }

        if (WebHelp.isAjAxRequest(request)) {

            ResultBean rb = new ResultBean();
            if (map.containsKey("isCaptcha")) {
                response.setHeader(RespHeaderConstans.AJAX_REQUEST_HEADER,
                        RespHeaderConstans.Code.AJAX_REQUEST_HEADER_004);
                rb.setSuccess(false);
                rb.setMessageCode(MessageCode.PLASS_CAPTCHA);
                rb.setMessage("请输入验证码");
            } else {
                response.setHeader(RespHeaderConstans.AJAX_REQUEST_HEADER,
                        RespHeaderConstans.Code.AJAX_REQUEST_HEADER_001);
                rb.setSuccess(false);
                rb.setMessageCode(MessageCode.PLASS_LOGIN);
                rb.setMessage("请登陆系统");
            }

            WebHelp.responseResultBean(request, response, rb);
        } else {
            try {
                if (map.containsKey("isCaptcha")) {
                    response.sendRedirect(request.getContextPath() + "/views/login.html?isCaptcha=1");
                } else {
                    response.sendRedirect(request.getContextPath() + "/views/login.html");

                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @RequestMapping(value = "unauthorized") // , method=RequestMethod.POST
    public void unauthorized(HttpServletRequest request, HttpServletResponse response) {
        if (WebHelp.isAjAxRequest(request)) {
            ResultBean rb = new ResultBean();
            response.setHeader(RespHeaderConstans.AJAX_REQUEST_HEADER, RespHeaderConstans.Code.AJAX_REQUEST_HEADER_002);
            rb.setSuccess(false);
            rb.setMessageCode(MessageCode.SYS_NO_PERMISSE);
            rb.setMessage("没有权限");
            WebHelp.responseResultBean(request, response, rb);
        } else {
            try {
                response.sendRedirect(request.getContextPath() + "/views/401.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    // @RequestMapping(value = "/login")
    public String showLoginForm(HttpServletRequest req, Model model) {
        String exceptionClassName = (String) req.getAttribute("shiroLoginFailure");
        String error = null;
        if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误";
        } else if (exceptionClassName != null) {
            error = "其他错误：" + exceptionClassName;
        }
        model.addAttribute("error", error);
        return "login";
    }

    @RequestMapping("/")
    public String index(@CurrentUser User loginUser) {
        if (loginUser == null) {
            return "/loginPage";
        }
//		List<Menu> menus = userService.getUserMenus(loginUser.getUserName());
        // model.addAttribute("menus", menus);
        // return "/views/main.html";
        return "/views/index.html";

    }

    @RequestMapping("/welcome")
    public String welcome() {
        return "welcome";
    }

    private ResultBean capthchaProcess(HttpServletRequest request, String userName, String captcha)

    {
        ResultBean rb = null;

        // 是否需要验证码
        // or springCacheManager
        EhcacheCacheManager cacheManager = (EhcacheCacheManager) SysApplicationContext
                .getBean("cacheManager");
        Cache<String, AtomicInteger> cache = cacheManager.getCache(EhCacheKeys.LONGIN_COUNT);
        AtomicInteger loginCount = cache.get(userName);
        if (loginCount != null && loginCount.get() >= SysComm.USER_LOGIN_COUNT) {
            if (StringUtils.isBlank(captcha)) {
                rb = new ResultBean(false, MessageCode.PLASS_CAPTCHA, "请输入验证码", "");
                return rb;
            }

            boolean captchaResult = Jcaptcha.validateResponse(request, captcha);
            if (!captchaResult) {
                System.out.println(captchaResult);
                rb = new ResultBean(false, MessageCode.CAPTCHA_ERROR, "验证码不正确", "");
                return rb;
            }
        }

        return rb;
    }

    /**
     * 异常处理
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "exception") // , method=RequestMethod.POST
    public void exception(HttpServletRequest request, HttpServletResponse response) {
        if (WebHelp.isAjAxRequest(request)) {
            ResultBean rb = new ResultBean();
            response.setHeader(RespHeaderConstans.AJAX_REQUEST_HEADER, RespHeaderConstans.Code.AJAX_REQUEST_HEADER_003);
            rb.setSuccess(false);
            rb.setMessageCode(MessageCode.SYS_ERROR);
            rb.setMessage("系统异常");
            WebHelp.responseResultBean(request, response, rb);
        } else {
            try {
                response.sendRedirect(request.getContextPath() + "/views/500.html");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}
